import traceback
from datetime import datetime

from cacheout import LFUCache

from sam.util import csvUtil
from sam.util.logUtil import get_info_logger
from sam.util.notifyUtil import WorkWeChartNotifyUtil, work_we_chart_notify

logger = get_info_logger()

# 定义一个全局缓存 采用最近最少使用机制
GLOBAL_CACHE = LFUCache(maxsize=5000)


def _assert_param_non_null(*args, **kwargs):
    b1 = True
    if args:
        for a in args:
            if not a:
                b1 = False
                break
    b2 = True
    if kwargs:
        for m in kwargs:
            if not m:
                b2 = False
                break

    return b1 and b2


def param_null_not_execute(func):
    """
     判断 传入 的 参数 是否 为 空 ， 空 则 不执行
    """

    def wrapper(*args, **kwargs):
        if _assert_param_non_null(*args, **kwargs):
            return func(*args, **kwargs)
        else:
            msg = f"出现异常: 参数是 {args} {kwargs}, 有参数为空"
            raise RuntimeError(msg)

    return wrapper


def catch_and_print_exception(func):
    """
     捕获 或 打印 异常
    """

    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except (Exception, RuntimeError, TypeError, NameError, AttributeError, Warning) as e:
            logger.error(f"出现异常: {e} 参数是 {args} 和 {kwargs}")
            logger.error(traceback.print_exc())

    return wrapper


def catch_and_notify_exception(func):
    """
     捕获 或 打印 异常
    """

    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except (Exception, RuntimeError, TypeError, NameError, AttributeError, Warning) as e:
            msg = f"参数是 {args} {kwargs}: 出现异常: {e} "
            logger.error(msg)
            work_we_chart_notify(msg)
            logger.error(traceback.print_exc())

    return wrapper


def deprecated(tips: str = None):
    """
     声明该方法 已经被废弃 将不会被执行
    """

    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            if str:
                print(f"该方法已被弃用，将不会被执行。{tips}")

            raise RuntimeWarning(f"该方法已被弃用，将不会被执行。")

        return inner_wrapper

    return wrapper


def warning(tips: str = None):
    '''
    声明该方法 已经被废弃 将不会被执行
    :param tips: 提示的内容
    :param func:
    :return:
    '''
    if tips:
        msg = f"该方法还存在问题： {tips} ，使用时请注意."
    else:
        msg = f"该方法还存在问题，使用时请注意."

    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            print(msg)
            func(*args, **kwargs)

        return inner_wrapper

    return wrapper


def print_task_cost_time(func):
    """
      打印 任务耗时时间
    """

    def wrapper(*args, **kwargs):
        print("程序开始执行，任务执行结束后，将输出任务执行时间...")
        start_time = datetime.now()
        func(*args, **kwargs)
        end_time = datetime.now()
        cost_time = (end_time - start_time).seconds
        # cost_time = (end_time - start_time).microseconds/1000
        print(f"执行完了, 此次任务, 耗时：{cost_time} 秒")

    return wrapper


def transfer_iterator_to_list(func):
    """
    将迭代器中的元素转换成list
    """

    def wrapper():
        def inner_wrapper(*args, **kwargs):
            rows = func(*args, **kwargs)
            result = []
            for row in rows:
                result.append(list(row))
            return result

        return inner_wrapper

    return wrapper()


def export_to_file(export_file_path: str, option: str = None):
    """
    传入 导出文件目标路径 就能  导出 scv文件
    """

    if not option:
        option = "cover"

    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            rows = func(*args, **kwargs)
            if rows:
                result = []
                for row in rows:
                    if row:
                        result.append(list(row))
                else:
                    csvUtil.csv_write(export_file_path, result, optional=option)
            else:
                print("没有可以导出的内容。")

        return inner_wrapper

    return wrapper


def send_notify(func):
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
        WorkWeChartNotifyUtil.Text().quick_notify(f"方法 {func.__name__} 执行 完成")

    return wrapper


def cache(name: str = None):
    """
    新增缓存装饰器
    """

    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            cache_key_prefix = name if name else func.__name__
            suffix = "_".join(*args)
            cache_key = f"{cache_key_prefix}_{suffix}"
            cache_value = GLOBAL_CACHE.get(cache_key, {})
            if cache_value:
                logger.info(f" key: {cache_key} 命中缓存，直接返回结果: {cache_value}")
                return cache_value
            result = func(*args, **kwargs)
            GLOBAL_CACHE.add(cache_key, result)
            logger.info(f" key: {cache_key} 没有命中缓存, 执行后返回结果: {result}")
            return result

        return inner_wrapper

    return wrapper


def cache_inner(func):
    """
    新增缓存装饰器
    """

    def wrapper(obj, *args, **kwargs):
        cache_key_prefix = func.__name__
        args = [str(arg) for arg in args]
        suffix = "_".join(args)
        cache_key = f"{cache_key_prefix}_{suffix}"
        cache_value = GLOBAL_CACHE.get(cache_key, {})
        if cache_value:
            logger.debug(f" key: {cache_key} 命中缓存，直接返回结果: {cache_value}")
            return cache_value
        result = func(obj, *args, **kwargs)
        GLOBAL_CACHE.add(cache_key, result)
        logger.debug(f" key: {cache_key} 没有命中缓存, 执行后返回结果: {result}")
        return result

    return wrapper


def retry_by_special_exception(exception=Exception, max_retry_times=3):
    """
     针对指定异常进行尝试
    """

    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            attempts = 1
            while attempts <= max_retry_times:
                try:
                    return func(*args, **kwargs)
                except exception as e:
                    logger.error(traceback.print_exc())
                    logger.info(f" 发生指定异常: {e} , 将进行第 {attempts} 次 尝试")
                    attempts += 1
            else:
                logger.info(f" 发生指定异常: {exception} , 在 {max_retry_times} 次 尝试失败后 退出尝试")

        return inner_wrapper

    return wrapper
